package net.cl.support.json;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import net.cl.Constants;
import net.cl.tools.HttpProxy;

public class JsonArray implements Json {

	private static final long serialVersionUID = 9208564592077176065L;
	private List<Json> jsonArray;
	private int level = 1;

	public JsonArray() {
		jsonArray = new ArrayList<Json>();
	}

	protected JsonArray(String json) {
		this();
	}

	public static JsonArray fromString(String json) {
		JsonBuilder jb = new JsonBuilder(json);
		jb.validate();
		return (JsonArray) jb.build();
	}
	
	public static JsonArray connect(String url) {
		HttpProxy p = new HttpProxy(url);
		try {
			return fromString(p.get());
		} catch (IOException e) {
			throw new JsonException("Connect to specified url error : " + url, e);
		}
	}

	private JsonElement getJsonElement(int index) {
		return (JsonElement) get(index);
	}

	public String getString(int index) {
		return getJsonElement(index).getValue();
	}

	public long getLong(int index) {
		return getJsonElement(index).toLong();
	}

	public double getDouble(int index) {
		return getJsonElement(index).toDouble();
	}

	public boolean getBoolean(int index) {
		return getJsonElement(index).toBoolean();
	}

	public JsonObject getJsonObject(int index) {
		return (JsonObject) get(index);
	}

	public JsonObject[] getJsonObjects() {
		return jsonArray.toArray(new JsonObject[0]);
	}

	public JsonArray addJson(Json json) {
		return addJson(-1, json);
	}

	public JsonArray addJson(int index, Json json) {
		if (json instanceof JsonObject)
			((JsonObject) json).setLevel(level + 1);
		else if (json instanceof JsonArray)
			((JsonArray) json).setLevel(level + 1);
		if (index == -1)
			jsonArray.add(json);
		else
			jsonArray.add(index, json);
		return this;
	}

	public JsonArray addString(String value) {
		jsonArray.add(new JsonElement(value));
		return this;
	}

	public JsonArray addString(int index, String value) {
		jsonArray.add(index, new JsonElement(value));
		return this;
	}

	public JsonArray addNumber(Number value) {
		jsonArray.add(new JsonElement(value));
		return this;
	}

	public JsonArray addNumber(int index, Number value) {
		jsonArray.add(index, new JsonElement(value));
		return this;
	}

	public JsonArray addBoolean(boolean value) {
		jsonArray.add(new JsonElement(value));
		return this;
	}

	public JsonArray addBoolean(int index, boolean value) {
		jsonArray.add(index, new JsonElement(value));
		return this;
	}

	public JsonArray addNull() {
		jsonArray.add(new JsonElement("null", false));
		return this;
	}

	public JsonArray addNull(int index) {
		jsonArray.add(index, new JsonElement("null", false));
		return this;
	}

	public JsonArray remove(int index) {
		jsonArray.remove(index);
		return this;
	}

	public int size() {
		return jsonArray.size();
	}

	public String toString() {
		return toString(false);
	}

	public String toTidyString() {
		return toString(true);
	}

	private String toString(boolean tidy) {
		StringBuilder sb = new StringBuilder();
		if (tidy) {
			for (int j = 0; j < level - 1; j++) {
				sb.append("  ");
			}
		}
		sb.append('[');
		int i = 1;
		for (Json json : jsonArray) {
			if (tidy && json instanceof JsonElement)
				sb.append(Constants.LINE_SEPARATOR);
			if (tidy) {
				for (int j = 0; j < level; j++) {
					sb.append("  ");
				}
				if (json instanceof JsonObject) {
					sb.append(Constants.LINE_SEPARATOR);
					sb.append(((JsonObject) json).toTidyString());
				} else if (json instanceof JsonArray) {
					sb.append(Constants.LINE_SEPARATOR);
					sb.append(((JsonArray) json).toTidyString());
				} else
					sb.append(json.toString());
			} else
				sb.append(json.toString());
			if (i < jsonArray.size())
				sb.append(',');
			i++;
		}
		if (tidy) {
			sb.append(Constants.LINE_SEPARATOR);
			for (int j = 0; j < level - 1; j++) {
				sb.append("  ");
			}
		}
		sb.append(']');
		return sb.toString();
	}

	private Json get(int index) {
		if (index >= jsonArray.size())
			throw new JsonException("The array index is not exist. " + index);
		return jsonArray.get(index);
	}

	protected void setLevel(int level) {
		this.level = level;
	}

}
